﻿using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.OpenApi.Models;

namespace NET6Demo.WebApi.Utility.Swagger
{
    /// <summary>
    /// 扩展
    /// </summary>
    public static class SwaggerExtension
    {
        /// <summary>
        /// Swagger完整配置
        /// </summary>
        public static void AddSwaggerGenExt(this WebApplicationBuilder builder)
        {
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen(option =>
            {
                #region 自定义分版本的Swagger配置
                {
                    ////要启用swagger版本控制要在api控制器或者方法上添加特性[ApiExplorerSettings(GroupName = "版本号")]  我这里是枚举
                    //typeof(ApiVersions).GetEnumNames().ToList().ForEach(version =>
                    //{
                    //    option.SwaggerDoc(version, new OpenApiInfo()
                    //    {
                    //        Title = $"{version}:Api文档",
                    //        Version = version,
                    //        Description = $"通用版本的CoreApi版本{version}"
                    //    });
                    //}); 

                }
                #endregion

                #region 组件支持版本展示
                {
                    // 根据 API 版本信息生成 API 文档 
                    var provider = builder.Services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
                    foreach (var description in provider.ApiVersionDescriptions)
                    {
                        option.SwaggerDoc(description.GroupName, new OpenApiInfo
                        {
                            Contact = new OpenApiContact
                            {
                                Name = "Richard老师",
                                Email = "18672713698@163..com"
                            },
                            Description = "朝夕教育 .NET6 WebAPI 文档",
                            Title = "朝夕教育 .NET6 WebAPI 文档",
                            Version = description.ApiVersion.ToString()
                        });
                    }
                    // 在 Swagger 文档显示的 API 地址中将版本信息参数替换为实际的版本号
                    option.DocInclusionPredicate((version, apiDescription) =>
                    {
                        if (!version.Equals(apiDescription.GroupName))
                            return false;

                        IEnumerable<string> values = apiDescription!.RelativePath
                            .Split('/')
                            .Select(v => v.Replace("v{version}", apiDescription.GroupName));
                        apiDescription.RelativePath = string.Join("/", values);
                        return true;
                    });

                    // 参数使用驼峰命名方式
                    option.DescribeAllParametersInCamelCase();
                    // 取消 API 文档需要输入版本信息
                    option.OperationFilter<RemoveVersionFromParameter>();
                }
                #endregion

                #region 配置展示注释
                {
                    // xml文档绝对路径 
                    var file = Path.Combine(AppContext.BaseDirectory, "NET6Demo.WebApi.xml");
                    //true : 显示控制器层注释
                    option.IncludeXmlComments(file, true);
                    //对action的名称进行排序，如果有多个，就可以看见效果了。
                    option.OrderActionsBy(o => o.RelativePath);
                }
                #endregion

                #region 扩展传入Token
                {
                    //添加安全定义
                    option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                    {
                        Description = "请输入token,格式为 Bearer xxxxxxxx（注意中间必须有空格）",
                        Name = "Authorization",
                        In = ParameterLocation.Header,
                        Type = SecuritySchemeType.ApiKey,
                        BearerFormat = "JWT",
                        Scheme = "Bearer"
                    });
                    //添加安全要求
                    option.AddSecurityRequirement(new OpenApiSecurityRequirement {
        {
            new OpenApiSecurityScheme
            {
                Reference =new OpenApiReference()
                {
                    Type = ReferenceType.SecurityScheme,
                    Id ="Bearer"
                }
            },
            new string[]{ }
        }
     });
                }
                #endregion

                #region 扩展文件上传按钮
                {
                    option.OperationFilter<FileUploadFilter>();
                }
                #endregion
            });
        }

        /// <summary>
        /// swagger中间件配置应用
        /// </summary>
        /// <param name="app"></param>
        public static void UseSwaggerExt(this WebApplication app)
        {
            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                #region 自定义支持API分版本展示
                {
                    //foreach (string version in typeof(ApiVersions).GetEnumNames())
                    //{
                    //    c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"版本：{version}");
                    //}
                }
                #endregion

                #region 调用第三方程序包支持版本控制
                {
                    var provider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
                    // 默认加载最新版本的 API 文档
                    foreach (var description in provider.ApiVersionDescriptions.Reverse())
                    {
                        c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
                            $"朝夕教育 API {description.GroupName.ToUpperInvariant()}");
                    }
                }
                #endregion

            });
        }

    }
}
